package service

import (
	"context"
	"dubbo.apache.org/dubbo-go/v3/config"
	_ "dubbo.apache.org/dubbo-go/v3/imports"
	"encoding/json"
	"github.com/dubbogo/grpc-go/codes"
	"github.com/dubbogo/grpc-go/status"
	_ "github.com/go-sql-driver/mysql"
	"message/api"
	"strconv"
	"time"
)

var (
	commentProvider *api.CommonClientImpl
)

type MessageServerImpl struct {
	api.UnimplementedMessageProviderServer
}

func OK(value []*api.Message) (*api.MessageList, error) {
	return &api.MessageList{
		List: value,
	}, nil
}

func FAIL(err error) (*api.MessageList, error) {
	return nil, err
}

func (s *MessageServerImpl) Add(c context.Context, message *api.Message) (*api.MessageList, error) {
	if message.UserAId == 0 || message.UserBId == 0 {
		return FAIL(status.Errorf(codes.FailedPrecondition, "parameter error"))
	}

	if message.UserAId > message.UserBId {
		return s.Add(c, &api.Message{
			UserAId: message.UserBId,
			UserBId: message.UserAId,
			Content: message.Content,
		})
	}

	_, err := commentProvider.Update(c, &api.Value{
		Database: "douyin",
		Table:    "message",
		Key:      []string{"user_a_id", "user_b_id", "content", "create_time"},
		Value:    []string{strconv.FormatInt(message.UserAId, 10), strconv.FormatInt(message.UserBId, 10), message.Content, strconv.FormatInt(time.Now().Unix(), 10)},
	})
	if err != nil {
		return FAIL(err)
	}

	return OK(nil)
}

func (s *MessageServerImpl) Del(c context.Context, message *api.Message) (*api.MessageList, error) {
	if message.Id == 0 {
		return FAIL(status.Errorf(codes.FailedPrecondition, "parameter error"))
	}

	_, err := commentProvider.Del(c, &api.Query{
		Database: "douyin",
		Table:    "message",
		Where: []*api.Query_Condition{
			{
				Key:   []string{"id"},
				Value: []string{strconv.FormatInt(message.Id, 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE},
			},
		},
	})
	if err != nil {
		return FAIL(err)
	}

	return OK(nil)
}

func (s *MessageServerImpl) Find(c context.Context, message *api.Message) (*api.MessageList, error) {
	if message.UserAId == 0 {
		return FAIL(status.Errorf(codes.FailedPrecondition, "parameter error"))
	}

	bytes, err := commentProvider.Get(c, &api.Query{
		Database: "douyin",
		Table:    "message",
		Key:      []string{"id", "user_a_id", "user_b_id", "content", "create_time"},
		Where: []*api.Query_Condition{
			{
				Key:   []string{"user_a_id"},
				Value: []string{strconv.FormatInt(message.UserAId, 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE},
			},
			{
				Key:   []string{"user_b_id"},
				Value: []string{strconv.FormatInt(message.UserAId, 10)},
				Type:  []api.Query_Condition_ConditionType{api.Query_Condition_NE},
			},
		},
		OrderBy: []*api.Query_Order{
			{
				Key:  "create_time",
				Type: api.Query_Order_DESC,
			},
		},
		Result: api.Query_MESSAGE,
	})
	if err != nil {
		return FAIL(err)
	}

	var list []*api.Message
	err = json.Unmarshal(bytes.Value, &list)
	if err != nil {
		return FAIL(err)
	}

	return OK(list)
}

func init() {
	commentProvider = new(api.CommonClientImpl)

	config.SetProviderService(&MessageServerImpl{})
	config.SetConsumerService(commentProvider)
}
